package repository

import (
	v1 "server_go/api/v1"
	"server_go/internal/model"
)

type ArticleRepository interface {
	GetArticleById(articleId int64) (*model.Article, error)
	GetArticleByTagId(tagId int64, page, pageSize int) ([]*model.Article, int64, error)
	GetArticleByUserId(userId int64, page, pageSize int) ([]*model.Article, int64, error)
	AddArticle(article *model.Article) error
	DeleteArticle(articleId int64) error
	UpdateArticle(articleId int64, article *model.Article) error
	GetAllArticle(page, pageSize int) ([]*model.Article, int64, error)
	GetAllArticleList(page, pageSize int) ([]*model.Article, int64, error)
	GetArticleByTitle(title string, page, pageSize int) ([]*model.Article, int64, error)
}

func NewArticleRepository(repository *Repository) ArticleRepository {
	return &articleRepository{
		Repository: repository,
	}
}

type articleRepository struct {
	*Repository
}

func (r *articleRepository) GetArticleById(articleId int64) (*model.Article, error) {
	var count int64
	if err := r.db.Table("article").
		Where("id = ? AND deleted_at IS NULL", articleId).
		Count(&count).Error; err != nil {
		return nil, err
	}
	if count == 0 {
		return nil, v1.ErrArticleNotExist
	}
	var article *model.Article
	if err := r.db.Table("article").Where("id = ?", articleId).First(&article).Error; err != nil {
		return nil, err
	}
	return article, nil
}

func (r *articleRepository) GetArticleByTagId(tagId int64, page, pageSize int) ([]*model.Article, int64, error) {
	articles := make([]*model.Article, 0)
	offset := (page - 1) * pageSize
	if err := r.db.Table("article").
		Where("tag_id = ? AND status = 1", tagId).
		Limit(pageSize).Offset(offset).Find(&articles).Error; err != nil {
		return nil, 0, err
	}
	var total int64
	if err := r.db.Table("article").
		Where("tag_id = ? AND deleted_at IS NULL", tagId).
		Count(&total).Error; err != nil {
		return nil, 0, err
	}
	return articles, total, nil
}

func (r *articleRepository) GetArticleByUserId(userId int64, page, pageSize int) ([]*model.Article, int64, error) {
	articles := make([]*model.Article, 0)
	offset := (page - 1) * pageSize
	if err := r.db.Table("article").
		Where("author_id = ?", userId).
		Limit(pageSize).Offset(offset).Find(&articles).Error; err != nil {
		return nil, 0, err
	}
	var count int64
	if err := r.db.Table("article").
		Where("author_id = ? AND deleted_at IS NULL", userId).
		Count(&count).Error; err != nil {
		return nil, 0, err
	}
	return articles, count, nil
}

func (r *articleRepository) AddArticle(article *model.Article) error {
	if err := r.db.Table("article").Create(&article).Error; err != nil {
		return err
	}
	return nil
}

func (r *articleRepository) DeleteArticle(articleId int64) error {
	if err := r.db.Table("article").Delete(&model.Article{}, articleId).Error; err != nil {
		return err
	}
	return nil
}

func (r *articleRepository) UpdateArticle(articleId int64, article *model.Article) error {
	updates := make(map[string]interface{})
	if article.TagId != 0 {
		updates["tag_id"] = article.TagId
	}
	if article.Title != "" {
		updates["title"] = article.Title
	}
	if article.Describe != "" {
		updates["describe"] = article.Describe
	}
	if article.MdContent != "" {
		updates["md_content"] = article.MdContent
	}
	if article.Status != 0 {
		updates["status"] = article.Status

	}
	if err := r.db.Table("article").Where("id = ?", articleId).Updates(updates).Error; err != nil {
		return err
	}
	return nil
}

func (r *articleRepository) GetAllArticle(page, pageSize int) ([]*model.Article, int64, error) {
	articles := make([]*model.Article, 0)
	offse := (page - 1) * pageSize
	if err := r.db.Table("article").
		Where("status = 1").
		Offset(offse).Limit(pageSize).Find(&articles).Error; err != nil {
		return nil, 0, err
	}
	var total int64
	if err := r.db.Table("article").
		Where("deleted_at IS NULL AND status = 1").
		Count(&total).Error; err != nil {
		return nil, 0, err
	}
	return articles, total, nil
}

func (r *articleRepository) GetAllArticleList(page, pageSize int) ([]*model.Article, int64, error) {
	articles := make([]*model.Article, 0)
	offse := (page - 1) * pageSize
	if err := r.db.Table("article").
		Offset(offse).Limit(pageSize).Find(&articles).Error; err != nil {
		return nil, 0, err
	}
	var total int64
	if err := r.db.Table("article").
		Where("deleted_at IS NULL AND status = 1").
		Count(&total).Error; err != nil {
		return nil, 0, err
	}
	return articles, total, nil
}

func (r *articleRepository) GetArticleByTitle(title string, page, pageSize int) ([]*model.Article, int64, error) {
	articles := make([]*model.Article, 0)
	offset := (page - 1) * pageSize
	if err := r.db.Table("article").
		Where("title LIKE ?", "%"+title+"%").
		Limit(pageSize).Offset(offset).Find(&articles).Error; err != nil {
		return nil, 0, err
	}
	var total int64
	if err := r.db.Table("article").
		Where("title LIKE ? AND deleted_at IS NULL", "%"+title+"%").
		Count(&total).Error; err != nil {
		return nil, 0, err
	}
	return articles, total, nil
}
